package com.yunchang.springboot.scheduled.mwsfinance;

import com.yunchang.springboot.base.BaseService;
import com.yunchang.springboot.mapper.mwsfinance.FInventoryDailyMapper;
import com.yunchang.springboot.mapper.mwsreport.MwsDailyInventoryHistoryMapper;
import com.yunchang.springboot.mapper.mwsreport.MwsMonthlyInventoryHistoryMapper;
import com.yunchang.springboot.models.mwsfinance.FAdjustmentInventoryMonthly;
import com.yunchang.springboot.models.mwsfinance.FInventoryDaily;
import com.yunchang.springboot.models.mwsreportbean.MwsMonthlyInventoryHistory;
import com.yunchang.springboot.utils.DateUtil;
import com.yunchang.springboot.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 期末盘库
 *
 * @author Administrator
 */
@Component
@Configuration
@Service
@Slf4j
@EnableScheduling
public class FAdjustmentInventoryMonthlyScheduled extends BaseService {

    private List<String> EUROPE_COUNTRY_NAME = Arrays.asList("DE", "UK", "FR", "IT", "ES");

    static final String US = "US";

    static final String CA = "CA";

    static final String MX = "MX";

    static final String JP = "JP";

    static final String SELL_ABLE = "SELLABLE";

    static Integer LIMIT_VALUE = 10000;

    static String DOCUMENTS_ID = "QMPKD";

    /**
     * 出入库明细
     */
    @Autowired
    FInventoryDetailsScheduled fInventoryDetailsScheduled;

    /**
     * 每月库存数据，亚马逊原始数据（更新一次）
     */
    private MwsMonthlyInventoryHistoryMapper mwsMonthlyInventoryHistoryMapper;

    @Autowired
    public void setMwsMonthlyInventoryHistoryMapper(MwsMonthlyInventoryHistoryMapper mwsMonthlyInventoryHistoryMapper) {
        this.mwsMonthlyInventoryHistoryMapper = mwsMonthlyInventoryHistoryMapper;
    }

    /**
     * 库存数据
     */
    private FInventoryDailyMapper fInventoryDailyMapper;

    @Autowired
    public void setFInventoryDailyMapper(FInventoryDailyMapper fInventoryDailyMapper) {
        this.fInventoryDailyMapper = fInventoryDailyMapper;
    }


    /**
     * 每日库存记录原始数据
     */
    private MwsDailyInventoryHistoryMapper mwsDailyInventoryHistoryMapper;

    @Autowired
    public void setMwsDailyInventoryHistoryMapper(MwsDailyInventoryHistoryMapper mwsDailyInventoryHistoryMapper) {
        this.mwsDailyInventoryHistoryMapper = mwsDailyInventoryHistoryMapper;
    }

    public void getFAdjustmentInventoryMonthlyData(String date) {
        List<MwsMonthlyInventoryHistory> mwsMonthlyInventoryHistoryList = mwsMonthlyInventoryHistoryMapper.selectByFinanceStatus(1, null);
        List<String> warehouseList = Arrays.asList("140603", "140605", "140601");
        List<FInventoryDaily> fInventoryDailyList = fInventoryDailyMapper.selectByCreateTimeAndWarehouseAndIsEndAdjustment(DateUtil.getLastTimeMonth(new Date()), warehouseList, 1, null);
        // 存放期末盘库数据的集合
        List<FAdjustmentInventoryMonthly> fAdjustmentInventoryMonthlyList = new ArrayList<>();
        Integer mwsMonthlyInventoryHistoryListSize = mwsMonthlyInventoryHistoryList.size();
        if (mwsMonthlyInventoryHistoryListSize > LIMIT_VALUE) {
            log.info("期末盘库中根据每月库存记录生成财务数据的数据量：" + mwsMonthlyInventoryHistoryListSize);
            int forNum = 1;
            forNum += mwsMonthlyInventoryHistoryListSize / LIMIT_VALUE;
            for (; forNum > 0; forNum--) {
                log.info("期末盘库中根据每月库存记录生成的财务数据剩余次数：" + forNum);
                mwsMonthlyInventoryHistoryList = mwsMonthlyInventoryHistoryMapper.selectByFinanceStatus(1, LIMIT_VALUE);
                mwsMonthlyInventoryHistoryDispose(mwsMonthlyInventoryHistoryList, fAdjustmentInventoryMonthlyList);
            }
        } else {
            mwsMonthlyInventoryHistoryDispose(mwsMonthlyInventoryHistoryList, fAdjustmentInventoryMonthlyList);
        }

        Integer fInventoryDailyListSize = fInventoryDailyList.size();
        if (fInventoryDailyListSize > LIMIT_VALUE) {
            log.info("期末盘库中根据每日库存记录生成财务数据的数据量：" + fInventoryDailyListSize);
            int forNum = 1;
            forNum += fInventoryDailyListSize / LIMIT_VALUE;
            for (; forNum > 0; forNum--) {
                log.info("期末盘库中根据每日库存记录生成的财务数据剩余次数：" + forNum);
                fInventoryDailyList = fInventoryDailyMapper.selectByCreateTimeAndWarehouseAndIsEndAdjustment(DateUtil.getLastTimeMonth(new Date()), warehouseList, 1, LIMIT_VALUE);
                fInventoryDailyDispose(fInventoryDailyList, fAdjustmentInventoryMonthlyList);
            }
        } else {
            fInventoryDailyDispose(fInventoryDailyList, fAdjustmentInventoryMonthlyList);
        }

        // 对期末盘库数据进行去重
        List<Object> fAdjustmentInventoryMonthlyUniqueList = fAdjustmentInventoryMonthlyList.stream()
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                                        o -> o.getSellerId() + ";" + o.getCountry() + ";" + o.getCountry() + ";" + o.getSku() + ";" + o.getFnsku() + ";" + o.getWarehouse()))), ArrayList::new));
        try {
            baseInsertList(fAdjustmentInventoryMonthlyUniqueList);
            log.info("期末盘库财务数据已生成");
        } catch (Exception e) {
            log.error("插入数据时出现错误，期末盘库" + e);
            throw new RuntimeException("插入数据时出现错误，期末盘库");
        }
    }

    /**
     * 根据每日库存记录生成的期末盘库数据
     *
     * @param fInventoryDailyList
     * @param fAdjustmentInventoryMonthlyList
     */
    public void fInventoryDailyDispose(List<FInventoryDaily> fInventoryDailyList, List<FAdjustmentInventoryMonthly> fAdjustmentInventoryMonthlyList) {
        // 从库存中获取期末盘库数据
        if (null != fInventoryDailyList && !fInventoryDailyList.isEmpty()) {
            for (FInventoryDaily fInventoryDaily : fInventoryDailyList) {
                FAdjustmentInventoryMonthly fAdjustmentInventoryMonthly = new FAdjustmentInventoryMonthly();
                fAdjustmentInventoryMonthly.setIsInventoryDetails(1);
                fAdjustmentInventoryMonthly.setDocumentsId(DOCUMENTS_ID + UUIDUtil.getUUID());
                String sellerId = fInventoryDaily.getSellerId();
                fAdjustmentInventoryMonthly.setSellerId(sellerId);
                String country = fInventoryDaily.getCountry();
                fAdjustmentInventoryMonthly.setCountry(country);
                String month = fInventoryDaily.getDate().substring(0, 7);
                fAdjustmentInventoryMonthly.setMonth(month);
                String date = DateUtil.getFirstDayOfNextMonth(month, "yyyy-MM") + "-" + DateUtil.getTodayDate("yyyy-MM-dd").substring(8, 10);
                fAdjustmentInventoryMonthly.setDate(date);
                String sku = fInventoryDaily.getSku();
                fAdjustmentInventoryMonthly.setSku(sku);
                String fnSku = fInventoryDaily.getFnsku();
                fAdjustmentInventoryMonthly.setFnsku(fnSku);
                String warehouse = getWarehouseByInventory(fInventoryDaily.getWarehouse());
                fAdjustmentInventoryMonthly.setWarehouse(warehouse);
                Integer balance = getBalance(sellerId, sku, fnSku, month, country, warehouse);
                fAdjustmentInventoryMonthly.setBalance(balance);
                Integer quantity = Math.abs(balance);
                fAdjustmentInventoryMonthly.setQuantity(quantity);
                String debitSubjectId = getDebitSubjectId(balance, warehouse);
                fAdjustmentInventoryMonthly.setDebitSubjectId(debitSubjectId);
                String creditSubjectId = getCreditSubjectId(balance, warehouse);
                fAdjustmentInventoryMonthly.setCreditSubjectId(creditSubjectId);
                Map<String, Double> costUnitMap = getCostUnit(balance, sellerId, country, sku, date, debitSubjectId, creditSubjectId);
                Double costUnit = 0.0;
                if (costUnitMap.containsKey("costUnit1")) {
                    fAdjustmentInventoryMonthly.setCostUnit(costUnitMap.get("costUnit1"));
                    costUnit = costUnitMap.get("costUnit1");
                }
                if (costUnitMap.containsKey("costUnit2")) {
                    fAdjustmentInventoryMonthly.setStatus(2);
                    fAdjustmentInventoryMonthly.setCostUnit(costUnitMap.get("costUnit2"));
                    costUnit = costUnitMap.get("costUnit2");
                }
                fAdjustmentInventoryMonthly.setCostUnit(costUnit);
                fAdjustmentInventoryMonthly.setAmount(quantity * costUnit);
                fAdjustmentInventoryMonthly.setCurrency("RMB");
                fAdjustmentInventoryMonthly.setCreateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fAdjustmentInventoryMonthly.setUpdateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fAdjustmentInventoryMonthlyList.add(fAdjustmentInventoryMonthly);
                fInventoryDaily.setIsEndAdjustment(2);
            }
            fInventoryDailyMapper.updateIsEndAdjustmentByFInventoryDailyList(fInventoryDailyList);
        } else {
            log.info("未查询到对应的库存数据列表，时间为" + DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
        }
    }

    /**
     * 根据每月库存记录生成的期末盘库数据
     *
     * @param mwsMonthlyInventoryHistoryList
     * @param fAdjustmentInventoryMonthlyList
     */
    public void mwsMonthlyInventoryHistoryDispose(List<MwsMonthlyInventoryHistory> mwsMonthlyInventoryHistoryList, List<FAdjustmentInventoryMonthly> fAdjustmentInventoryMonthlyList) {
        // 从每月库存记录中获取期末盘库数据
        if (null != mwsMonthlyInventoryHistoryList && !mwsMonthlyInventoryHistoryList.isEmpty()) {
            for (MwsMonthlyInventoryHistory mwsMonthlyInventoryHistory : mwsMonthlyInventoryHistoryList) {
                FAdjustmentInventoryMonthly fAdjustmentInventoryMonthly = new FAdjustmentInventoryMonthly();
                fAdjustmentInventoryMonthly.setIsInventoryDetails(1);
                fAdjustmentInventoryMonthly.setDocumentsId(DOCUMENTS_ID + UUIDUtil.getUUID());
                String sellerId = mwsMonthlyInventoryHistory.getSellerId();
                String area = mwsMonthlyInventoryHistory.getArea();
                String fnSku = mwsMonthlyInventoryHistory.getFnsku();
                String countryByMwsMonthlyInventoryHistory = mwsMonthlyInventoryHistory.getCountry();
                fAdjustmentInventoryMonthly.setSellerId(sellerId);
                String country = getCountry(sellerId, area, countryByMwsMonthlyInventoryHistory, fnSku);
                fAdjustmentInventoryMonthly.setCountry(country);
                String sku = mwsMonthlyInventoryHistory.getSku();
                fAdjustmentInventoryMonthly.setSku(sku);
                fAdjustmentInventoryMonthly.setFnsku(mwsMonthlyInventoryHistory.getFnsku());
                String warehouse = getWarehouse(mwsMonthlyInventoryHistory.getDetailedDisposition());
                fAdjustmentInventoryMonthly.setWarehouse(warehouse);
                String month = mwsMonthlyInventoryHistory.getMonth();
                fAdjustmentInventoryMonthly.setMonth(month);
                String date = DateUtil.getFirstDayOfNextMonth(month, "yyyy-MM") + "-" + DateUtil.getTodayDate("yyyy-MM-dd").substring(8, 10);
                fAdjustmentInventoryMonthly.setDate(date);
                Integer balance = getBalance(sellerId, sku, fnSku, month, country, warehouse);
                if (balance == 0) {
                    continue;
                }
                fAdjustmentInventoryMonthly.setBalance(balance);
                Integer quantity = Math.abs(balance);
                fAdjustmentInventoryMonthly.setQuantity(quantity);
                String debitSubjectId = getDebitSubjectId(balance, warehouse);
                fAdjustmentInventoryMonthly.setDebitSubjectId(debitSubjectId);
                String creditSubjectId = getCreditSubjectId(balance, warehouse);
                fAdjustmentInventoryMonthly.setCreditSubjectId(creditSubjectId);
                fAdjustmentInventoryMonthly.setCurrency("RMB");
                Map<String, Double> costUnitMap = getCostUnit(balance, sellerId, country, sku, date, debitSubjectId, creditSubjectId);
                if(null != costUnitMap && !costUnitMap.isEmpty()){
                    Double costUnit = 0.0;
                    if (costUnitMap.containsKey("costUnit1")) {
                        fAdjustmentInventoryMonthly.setCostUnit(costUnitMap.get("costUnit1"));
                        costUnit = costUnitMap.get("costUnit1");
                    }
                    if (costUnitMap.containsKey("costUnit2")) {
                        fAdjustmentInventoryMonthly.setStatus(2);
                        fAdjustmentInventoryMonthly.setCostUnit(costUnitMap.get("costUnit2"));
                        costUnit = costUnitMap.get("costUnit2");
                    }
                    fAdjustmentInventoryMonthly.setAmount(new BigDecimal(quantity * costUnit).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }
                fAdjustmentInventoryMonthly.setCreateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fAdjustmentInventoryMonthly.setUpdateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fAdjustmentInventoryMonthlyList.add(fAdjustmentInventoryMonthly);
                mwsMonthlyInventoryHistory.setFinanceStatus(2);
            }
            mwsMonthlyInventoryHistoryMapper.updateFinanceStatusByMwsMonthlyInventoryHistoryList(mwsMonthlyInventoryHistoryList);
        } else {
            log.info("未查询到对应的每月库存记录数据列表，时间为" + DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
        }
    }

    /**
     * 根据参数获取country
     *
     * @param sellerId
     * @param area
     * @param country
     * @param fnSku
     * @return
     */
    public String getCountry(String sellerId, String area, String country, String fnSku) {
        String countryResult = null;
        if (area.equals(JP)) {
            return JP;
        }
        if (EUROPE_COUNTRY_NAME.contains(area)) {
            return "EU";
        }
        if (area.equals(US) && !StringUtils.isEmpty(fnSku) && !StringUtils.isEmpty(sellerId)) {
            if (!StringUtils.isEmpty(country)) {
                return country;
            } else {
                List<String> countryList = mwsDailyInventoryHistoryMapper.selectCountryByFuSkuAndSellerId(fnSku, sellerId);
                if (null != countryList && !countryList.isEmpty()) {
                    if (countryList.contains(US)) {
                        countryResult = US;
                    } else if (countryList.contains(CA)) {
                        countryResult = CA;
                    } else if (countryList.contains(MX)) {
                        countryResult = MX;
                    } else {
                        countryResult = US;
                    }
                } else {
                    countryResult = US;
                }
            }
        }
        return countryResult;
    }

    /**
     * 根据detailedDisposition获取warehouse的值
     *
     * @param detailedDisposition
     * @return
     */
    public String getWarehouse(String detailedDisposition) {
        if (!StringUtils.isEmpty(detailedDisposition)) {
            detailedDisposition = detailedDisposition.toUpperCase();
            if (detailedDisposition.equals(SELL_ABLE)) {
                return "140603";
            } else {
                return "140605";
            }
        }
        log.info("期末盘库从每月库存记录中获取warehouse中detailedDisposition为空");
        return null;
    }


    /**
     * 根据detailedDisposition获取warehouse的值
     *
     * @param warehouse
     * @return
     */
    public String getWarehouseByInventory(String warehouse) {
        List<String> warehouseList = Arrays.asList("140601", "140605");
        if (!StringUtils.isEmpty(warehouse)) {
            if (warehouseList.contains(warehouse)) {
                return "140605";
            } else {
                return "140603";
            }
        }
        log.info("期末盘库从每月库存记录中获取warehouse中detailedDisposition为空");
        return null;
    }

    /**
     * 获取balance
     *
     * @param sellerId
     * @param sku
     * @param fnSku
     * @param month
     * @param country
     * @param warehouse
     * @return
     */
    public int getBalance(String sellerId, String sku, String fnSku, String month, String country, String warehouse) {
        String warehouseValueOne = "140603";
        String warehouseValueTwo = "140605";
        if (!StringUtils.isEmpty(warehouse)) {
            if (warehouse.equals(warehouseValueOne)) {
                Integer endQuantity = mwsMonthlyInventoryHistoryMapper.selectSumEndQuantityBySellerIdAndSkuAndFnSkuAndMonthAndDetailedDisposition(sellerId, sku, fnSku, month, SELL_ABLE);
                Integer quantity = fInventoryDailyMapper.selectSumQuantityBySellerIdAndSkuAndFnSkuAndCountryAndDateAndWarehouseList(sellerId, country, sku, fnSku, Arrays.asList("140603"), "");
                if (null != endQuantity && null != quantity) {
                    return endQuantity - quantity;
                }
            }
            if (warehouse.equals(warehouseValueTwo)) {
                Integer endQuantity = mwsMonthlyInventoryHistoryMapper.selectSumEndQuantityBySellerIdAndSkuAndFnSkuAndMonthAndDetailedDispositionUnequal(sellerId, sku, fnSku, month, SELL_ABLE);
                Integer quantity = fInventoryDailyMapper.selectSumQuantityBySellerIdAndSkuAndFnSkuAndCountryAndDateAndWarehouseList(sellerId, country, sku, fnSku, Arrays.asList("140601", "140605"), "");
                if (null != endQuantity && null != quantity) {
                    return endQuantity - quantity;
                }
            }
        }
        return 1;
    }

    /**
     * 获取借方科目
     *
     * @param balance
     * @param warehouse
     * @return
     */
    public String getDebitSubjectId(Integer balance, String warehouse) {
        if (balance < 0) {
            return "660202";
        } else if (balance > 0) {
            return warehouse;
        } else {
            return null;
        }
    }

    /**
     * 获取贷方科目
     *
     * @param balance
     * @param warehouse
     * @return
     */
    public String getCreditSubjectId(Integer balance, String warehouse) {
        if (balance < 0) {
            return warehouse;
        } else if (balance > 0) {
            return "660201";
        } else {
            return null;
        }
    }

    /**
     * @param balance
     * @param sellerId
     * @param country
     * @param sku
     * @param date
     * @param debitSubjectId
     * @return 返回的map集合其key值是costUnit2则表示使用第二种方式得到的结果
     */
    public Map<String, Double> getCostUnit(Integer balance, String sellerId, String country, String sku, String date, String debitSubjectId, String creditSubjectId) {
        if (balance > 0) {
            Double amount = fInventoryDailyMapper.selectSumAmountBySellerIdAndCountryAndSkuAndCreditSubjectIdAndDate(sellerId, country, sku, debitSubjectId, date);
            Integer quantity = fInventoryDailyMapper.selectSumQuantityBySellerIdAndCountryAndSkuAndCreditSubjectIdAndDate(sellerId, country, sku, debitSubjectId, date);
            if (null != amount && null != quantity && amount != 0.0 && quantity != 0) {
                return new HashMap<String, Double>(1) {{
                    put("costUnit1", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }};
            }
            Map<String, Object> amountAndQuantityMap = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouseList(sellerId, country, sku, Arrays.asList("140603", "140605"));
            if (null != amountAndQuantityMap && !amountAndQuantityMap.isEmpty()) {
                if(null != amountAndQuantityMap.get("amount") && null != amountAndQuantityMap.get("quantity")){
                    Double amount4 = new Double(amountAndQuantityMap.get("amount").toString());
                    Integer quantity4 = new Integer(amountAndQuantityMap.get("quantity").toString());
                    if (null != amount4 && null != quantity4 && amount4 != 0 && quantity4 != 0) {
                        return new HashMap<String, Double>(1) {{
                            put("costUnit2", new BigDecimal(amount4 / quantity4).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                        }};
                    }
                }
            }
        }
        if (balance < 0) {
            Double amount = fInventoryDailyMapper.selectSumAmountBySellerIdAndCountryAndSkuAndCreditSubjectIdAndDate(sellerId, country, sku, creditSubjectId, date);
            Integer quantity = fInventoryDailyMapper.selectSumQuantityBySellerIdAndCountryAndSkuAndCreditSubjectIdAndDate(sellerId, country, sku, creditSubjectId, date);
            if (null != amount && null != quantity && amount != 0.0 && quantity != 0) {
                return new HashMap<String, Double>(1) {{
                    put("costUnit1", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }};
            }
            Map<String, Object> amountAndQuantityMap = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouseList(sellerId, country, sku, Arrays.asList("140603", "140605"));
            if (null != amountAndQuantityMap && !amountAndQuantityMap.isEmpty()) {
                if(null != amountAndQuantityMap.get("amount") && null != amountAndQuantityMap.get("quantity")){
                    Double amount4 = new Double(amountAndQuantityMap.get("amount").toString());
                    Integer quantity4 = new Integer(amountAndQuantityMap.get("quantity").toString());
                    if (null != amount4 && null != quantity4 && amount4 != 0 && quantity4 != 0) {
                        return new HashMap<String, Double>(1) {{
                            put("costUnit2", new BigDecimal(amount4 / quantity4).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                        }};
                    }
                }
            }
        }
        return null;
    }


}
